Create a series of User-Defined Functions (UDFs) to map ggplot2 syntax to base R
Record
Scatterplots
# define the ggplot objectggplot(data, aes(x = x, y = y)) +# fill coordinate pointsgeom_point(aes(x = x, y = y, size = size), shape = shape, color = color) +# set x limitsscale_x_discrete(limits = limits) +# set y limitsscale_y_continuous(limits = limits) +# set titles / axis labelslabs(title = title,subtitle = subtitle,x = x,y = y) +# set themetheme_bw() +# additional graphicstheme(legend.position ="none")
Match
# define the plot objectplot(x = x, y = y,# set x limitsxlim = scale_x_discrete,# set y limitsylim =scale_y_continuous(),# set titles / axis labelsmain = title, sub = subtitle,xlab =lab(x), ylab =lab(y),# point shape / size / colorpch = shape,cex = size,col = color)
UDFs
Plot and ggplot are dynamic
They adjust to optional parameters being passed or left out
# perfectly valid inputs that return full responsesplot(x = x, y = y)ggplot(data = data, aes(x = x, y = y)) +geom_point()
Optional Parameters
Every optional parameter is defaulted as NULL
I’ll use if (!is.null()) {} else {} statements to check
# generate the points## check for graphical conditions pch/col/cexif (!is.null(pch) &!is.null(col) &!is.null(cex)){# if present generate points with all graphical params points =geom_point(aes(x = x, y = y, size = cex), shape = pch, color = col)}# reduce as neededelseif (!is.null(cex) &!is.null(col)) {# color and size points =geom_point(aes(x = x, y = y, size = cex), color = col)}
Base Scatter
# ya know what?# *un-gg's your plot*ungg_scatter =function(x,y,data,pch=NULL,xlim=NULL,ylim=NULL, main,sub=NULL, xlab,ylab,col=NULL,cex=NULL,theme_choice=NULL){# so this is a monolith of code btw ## imagine not having it thorequire(ggplot2)# create the major ggplot object plt =ggplot(data, aes(x = x, y = y))# we remove the legend by default## it was so much effort to make this conditional### and i have thoroughly lost my mind doing this rm_legend =theme(legend.position ="none")# generate the points## check for graphical conditions pch/col/cexif (!is.null(pch) &!is.null(col) &!is.null(cex)){# if present generate points with all graphical params points =geom_point(aes(x = x, y = y, size = cex), shape = pch, color = col) }# reduce as neededelseif (!is.null(cex) &!is.null(col)) {# color and size points =geom_point(aes(x = x, y = y, size = cex), color = col) }elseif (!is.null(col) &!is.null(pch)) {# color and type points =geom_point(aes(x = x, y = y), shape = pch, color = col) }elseif (!is.null(col)) {# just color points =geom_point(aes(x = x, y = y), color = col) }elseif (!is.null(cex)) {# size points =geom_point(aes(x = x, y = y, size = cex)) }elseif (!is.null(pch)) {# shape points =geom_point(aes(x = x, y = y), shape = pch) }else {# default to raw point plotting points =geom_point(aes(x = x, y = y)) }# subtitle is the only optional label paramif (!is.null(sub)) {# produce with subtitle plt_labels =labs(title = main,subtitle = sub,x = xlab,y = ylab) }else {# produce without subtitle plt_labels =labs(title = main,x = xlab,y = ylab) }# limit checks, set scale for each axisif (!is.null(xlim) &!is.null(ylim)) {# if-else statement for x class ## if x is a continuous valueif (class(x) =="numeric") {# set x limit as continuous based on xlim xlimit =scale_x_continuous(limits = xlim) }# if x is any other typeelse {# convert x to numeric## this is a lazy safety for if x### is a character or factor or o.w. x =as.numeric(x)# set x limit as discrete based on xlim xlimit =scale_x_discrete(limits = xlim) }# if-else statement for y class ## if y is a continuous valueif (class(y) =="numeric") {# set y limit as continuous based on ylim ylimit =scale_y_continuous(limits = ylim) }# if y is any other typeelse {# convert y to numeric## lazy safety again### i know there's better ways#### but this function is already stupid##### why are you seeking l33t code here y =as.numeric(y) # im literally just a girl# set y limit as discrete based on ylim ylimit =scale_y_discrete(limits = xlim) } }# this part sucked to write## just a ton of checks for existing parameters### it's shockingly less time complex to reference the major variables#### instead of the existence of the ones produced by the functionif (!is.null(xlim) &!is.null(ylim) &!is.null(theme_choice)) { output_plot = plt + points + xlimit + ylimit + plt_labels + theme_choice + rm_legend }elseif (!is.null(theme_choice)) { output_plot = plt + points + plt_labels + theme_choice + rm_legend }else { output_plot = plt + points + plt_labels + rm_legend }# output should be saved as an object so extra layers can be added}
# line through pointsgeom_line()# horizontal linegeom_hline()# vertical linegeom_vline()# intercept + slope linegeom_abline()
I love lines
Base R has the same specifications, but it wraps it in two functions
# line through (or made from) pointspoints(x, y, type ="l", lwd = linewidth, lty = linetype, col = color)# horizontal/vertical/ablineabline(a = intercept, b = slope,h = horizontal, v = vertical,lwd = linewidth, lty = linetype, col = color)
Line Proto Objects
ungg_lines =function(x=NULL,y=NULL,h=NULL,v=NULL,ab=NULL,lcol=NULL,hcol=NULL,vcol=NULL,abcol=NULL, lwd,lty) {# i've learned a lot of ggplot doing this## ironicallyrequire(ggplot2)# these if-else statements be like:# lizard# lizard# if x and y are providedif (!is.null(x) &!is.null(y)){ # lizard# if color is specifiedif (!is.null(lcol)) { # lizard# produce lines with color lns =geom_line(aes(x = x, y = y),color = lcol,linewidth = lwd[1],linetype = lty[1]) }# o.w. without colorelse { # lizard# lines with no color lns =geom_line(aes(x = x, y = y), linewidth = lwd[1],linetype = lty[1]) } }# if hlines are specified## and a color is specifiedif (!is.null(h) &!is.null(hcol)) { # lizard# hline with color hlines =geom_hline(yintercept = h, color = hcol,linewidth = lwd[2], linetype = lty[2]) }# if its just an hlineelseif (!is.null(h)) { # lizard# give an hline hlines =geom_hline(yintercept = h,linewidth = lwd[2],linetype = lty[2]) }# if hlines are specified## and a color is specifiedif (!is.null(v) &!is.null(vcol)) { # lizard# vline with color vlines =geom_vline(xintercept = v,color = vcol,linewidth = lwd[3],linetype = lty[3]) }# if its just a vlineelseif (!is.null(v)) { # lizard# give a vline vlines =geom_vline(xintercept = v,linewidth = lwd[3],linetype = lty[3]) }# if an abline is specified## with a colorif (!is.null(abline) &!is.null(abcol)) { # lizard# abline with color ablines =geom_abline(intercept = ab[1], slope = ab[2],color = abcol,linewidth = lwd[4],linetype = lty[4]) }# just an abline?elseif (!is.null(abline)) { # lizard# no color for you ablines =geom_abline(intercept = ab[1],slope = ab[2],linewidth = lwd[4],linetype = lty[4]) }# .............................. .:-===----::.. ................................# ............................. .-++==----:::::::. ...............................# ........................... -+*+=--::::::::::::. ..............................# ..................... .-**+=--::::::.......:. ......... ........# .................. ..:--=*#*+==--:+*#*+-.......---:.. ....::.... .....# ............... .:=+*######*+==-:-#%###+.......=+++++=-:....:--------:::. ...# ............. .-=*#%%%#******++=--:=***+:......:++++++***++===--:::::::::::. ..# ........... .-+#%%%%%##****++++++==--::::::::-=++++++++++++==-:::::::.::::::. .# .......... .-*#%@@@@%%##*****+++++++++++++++++++++++++++++++=-::::....::....::.# ......... :+*%@@@@@@@%%##****++++++++++++++++++++++++++++++++=-:::..:+**+-...:.# ....... -*#%@@@%%@@@@%%##***+++++++++++++++++++++++++++++++++=-::..+###%+...:.# ...... .-##%@@@%##%@@@@@%%#***++++++++++++++++++++++++++++++++===-:.-+**+:...:..# ..... .=#%@@@@@%##%%%%@@@%%##***+++++++++++++++========++===========-:::...:-. .# .... .=%@@@@@@@%%%%%%%%%%%%%%##**++++++++==============++===+===========---=+=.# .... =%@@@@@@@@@%%%%%%%%###%%%%##**+++++++========----------=--===========++=+=.# ... -%@@@@@@@@@@@%%%%%%############***++++++=======-----------------============# .. :%@@@@@@@@@@@@%%%%%%%%####****+*******++++++======-------------------========# . .*@@@@@@@@@@@@@%%%%%%%%%%###***+++++++++++++++++======-----------------======:# . -@@@@@@@@@%%%%%%%%%%%%%%######**++++++=======+++++++======----------========:# .#@@@@@@@%%%%%#################****++++++==================================-. .# -@@@@@@%%%%#####*********************++++++=======-------------===========:. ..# .*@@@@@%%%####********+******************++++++=======-------------======:. ...# :%@@@@%%###******++++++++++++++++++******+++++++++====================-:. .....# =@@@@%%###***++++++++++++++++++++++++++++++++++++++++++++=====++===-:. .......# *@@@@%%##***+++++===================+++++++++++++++++++++++===-::.. ..........# +**####**+++++===========================================-:.. .............# # # # # # # # # # # # # # # # L I Z A R D # # # # # # # # # # # # # # # # # # ## line set ups for if theres x and y data specified## everything is saved as a list bc gg proto objects cant be combined### so you'll have to reference the list after the factif (!is.null(x) &!is.null(y)){ # lizardif (!is.null(h) &!is.null(v) &!is.null(ab)){ # lizard output_lines =list(lines = lns,hlines = hlines,vlines = vlines,ablines = ablines) }elseif (!is.null(h) &!is.null(v)){ # lizard output_lines =list(lines = lns,hlines = hlines,vlines = vlines) }elseif (!is.null(h) &!is.null(ab)){ # lizard output_lines =list(lines = lns,hlines = hlines,ablines = ablines) }elseif (!is.null(v) &!is.null(ab)){ # lizard output_lines =list(lines = lns,vlines = vlines,ablines = ablines) }elseif (!is.null(h)){ # lizard output_lines =list(lines = lns,hlines = hlines) }elseif (!is.null(v)){ # lizard output_lines =list(lines = lns,vlines = vlines) }elseif (!is.null(ab)){ # lizard output_lines =list(lines = lns,ablines = ablines) } }# if no x and y data is present we restart the checks## and save appropriatelyelse { # lizardif (!is.null(h) &!is.null(v) &!is.null(ab)){ # lizard output_lines =list(hlines = hlines,vlines = vlines,ablines = ablines) }elseif (!is.null(h) &!is.null(v)){ # lizard output_lines =list(hlines = hlines,vlines = vlines) }elseif (!is.null(h) &!is.null(ab)){ # lizard output_lines =list(hlines = hlines,ablines = ablines) }elseif (!is.null(v) &!is.null(ab)){ # lizard output_lines =list(vlines = vlines,ablines = ablines) }elseif (!is.null(h)){ # lizard output_lines =list(hlines = hlines) }elseif (!is.null(v)){ # lizard output_lines =list(vlines = vlines) }elseif (!is.null(ab)){ # lizard output_lines =list(ablines = ablines) } }}
# as.numeric(as.factor()) is my lazy trick## to make characters into integers### i know there's a better way #### i just can't bring myself to carex =as.numeric(as.factor(df$pt))# reproducibility seedset.seed(73)# puts a uniform distributed distance## on the values of x where each uniform### has min = -0.25 and max 0.25jit_x =jitter(x) # the documentation was weird# initialize drug names as numericsn_drug =sort(as.numeric(as.factor(df$Drug)))# log relative risklog_RR = df$log_RR# color scheme from scale_shape_manualpnt_colors =c("#CC9900", "#999900", "#66CC33", "#33CC66", "#00CC99", "#00CCCC", "#00CCFF", "#33CCFF", "#6699FF", "#9966FF", "#CC66CC", "#CC3399", "#FF6699", "#FF66CC")# control margins of graph## bottom, left, top, rightpar(mar =c(10,4,0.5,8)) # (i always forget)plot(jit_x,log_RR,pch =2:15, # shapescol = pnt_colors, # colorsxaxt ="n", # no x axis ticksxlab ="", # no x axis labelylab ="log Relative Risk", # y axis labelcex =1.3) # point size# build the gridabline(h =seq(0,3,1),col="#D1D1D190") # horizontalabline(v =seq(1,13,1),col="#D1D1D190") # vertical# x axis ticks with character labelsaxis(1, seq(1,13,1), labels =sort(unique(df$pt)),las =2, cex.axis =0.75)# x axis labelmtext("Pulmonary Adverse Events", 1, 9)# legend set to the rightlegend("right", legend =sort(unique(df$Drug)), # drug namescol = pnt_colors, # colorspch =2:15, # shapesbty ="n", # prevent legend boxpt.cex =1, # point sizecex =0.8, # text sizetext.col ="black", horiz = F, # prevent horizontal legendinset =c(-.2, .8), # hjust / vjustxpd = T) # required to set it outside of the plot box